package cn.itcast.n4_共享模型_管程;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import static cn.itcast.util.Sleeper.sleep;

//线程1:a
//线程2:b
//线程3:c

//线程1:a
//线程2:b
//线程3:c

//线程1:a
//线程2:b
//线程3:c
// 等待标记      输出内容   修改标记为
//    1            a         2
//    2            b         3
//    3            c         1
@Slf4j(topic = "c.Test49_$$$$$_设计模式之顺序控制_ReentrantLock实现3个线程交替输出abc五次")
public class Test49_$$$$$_设计模式之顺序控制_ReentrantLock实现3个线程交替输出abc五次 {

    public static void main(String[] args) {
        AwaitSignal1 awaitSignal1 = new AwaitSignal1(5);
        Condition aCondition = awaitSignal1.newCondition();
        Condition bCondition = awaitSignal1.newCondition();
        Condition cCondition = awaitSignal1.newCondition();

        Thread a = new Thread(() -> {
            awaitSignal1.print("a", aCondition, bCondition);
        }, "a");

        Thread b = new Thread(() -> {
            awaitSignal1.print("b", bCondition, cCondition);
        }, "b");

        Thread c = new Thread(() -> {
            awaitSignal1.print("c", cCondition, aCondition);
        }, "c");
        a.start();
        b.start();
        c.start();

        sleep(1);

        awaitSignal1.lock();
        try {
            aCondition.signal();
        }finally {
            awaitSignal1.unlock();
        }
    }
}

@Slf4j(topic = "c.AwaitSignal1")
class AwaitSignal1 extends ReentrantLock {
    private int loopNumber;

    public AwaitSignal1(int loopNumber) {
        this.loopNumber = loopNumber;
    }


    /**
     *
     * @param printData 打印内容
     * @param waitCondition 在哪个休息室休息
     * @param notifyCondition 唤醒哪个休息室
     */
    public void print(String printData,Condition waitCondition,Condition notifyCondition){
        for (int i = 0; i < loopNumber; i++) {
            this.lock();
            try {
                waitCondition.await();
                System.out.print(printData);
                notifyCondition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                this.unlock();
            }
        }
    }
}
